package com.dbex.core;

import java.sql.ResultSet;
import java.util.List;

import com.dbex.util.ArrayUtils;
import com.dbex.util.DBUtil;
import com.dbex.util.MainConfig;
import com.dbex.util.RowMapper;

public class MysqlDialect implements Dialect {
	
	private String FIND_ALL_TABLES = "SELECT it.`TABLE_NAME` FROM information_schema.`TABLES` it WHERE it.`TABLE_SCHEMA` = '";
	
	private String FIND_COLS_OF_TABLE = "SELECT ic.`COLUMN_NAME`,ic.`DATA_TYPE`,ic.`CHARACTER_MAXIMUM_LENGTH`,ic.`CHARACTER_OCTET_LENGTH`,ic.`NUMERIC_PRECISION`,ic.`NUMERIC_SCALE`,ic.`COLUMN_TYPE`  FROM information_schema.`COLUMNS` ic WHERE ic.`TABLE_SCHEMA` = ? AND ic.`TABLE_NAME` = ?";
	
	private static String DATE_FORMAT = "%Y-%m-%d %H:%i:%s";

	@SuppressWarnings({ "rawtypes"})
	@Override
	public Table[] getAllTables() {
		String srcSchema = MainConfig.getValue("src.schema");
		List list= DBUtil.queryList(FIND_ALL_TABLES+srcSchema+"'");
		Table[] tables = new Table[list.size()];
		for (int i = 0; i < list.size(); i++) {
			String tableName = list.get(i).toString();
			Column[] columns= DBUtil.queryList(FIND_COLS_OF_TABLE, new RowMapper<Column>(){

				@Override
				public Column rowMapper(ResultSet rs) throws Exception {
					Column column = new Column();
					column.setColumnName(rs.getString(1));
					String type = rs.getString(2);
					if("varchar".equals(type)){
						column.setColumnType("string");
						column.setVar(true);
					}else if ("char".equals(type)) {
						column.setColumnType("string");
						column.setVar(false);
					}else if (ArrayUtils.contains(new String[]{"int","double","byte"}, type)) {
						column.setColumnType("number");
						String typeStr = rs.getString(7);
						String mid = typeStr.substring(typeStr.indexOf('(')+1, typeStr.length()-1);
						if(mid.indexOf(',')==-1){
							column.setPrecision(Integer.valueOf(mid));
							column.setScale(0);
						}else{
							String[] strArr = mid.split(",");
							column.setPrecision(Integer.valueOf(strArr[0]));
							column.setScale(Integer.valueOf(strArr[1]));
						}
//						column.setPrecision(rs.getInt(5));
//						column.setScale(rs.getInt(6));
					}else if ("date".equals(type)) {
						column.setColumnType("date");
					}else{
						throw new RuntimeException("不识别的类型:"+type);
					}
					column.setLength(rs.getInt(3));
					return column;
				}
				
			}, srcSchema, tableName).toArray(new Column[0]);
			tables[i] = new Table(srcSchema,tableName,columns);
		}
		return tables;
	}
	
	public String toChar(String columnName){
		return "DATE_FORMAT("+columnName+",'"+DATE_FORMAT+"')";
	}

	@Override
	public String toDate(String columnValue) {
		return "STR_TO_DATE('"+columnValue+"','"+DATE_FORMAT+"')";
	}
	
	@Override
	public boolean isString(String columnType) {
		return ArrayUtils.contains(new String[]{"varchar","char"}, columnType);
	}

	@Override
	public boolean isNumber(String columnType) {
		return ArrayUtils.contains(new String[]{"int","float","double","byte","bigint"}, columnType);
	}

	@Override
	public boolean isDate(String columnType) {
		return ArrayUtils.contains(new String[]{"date","datetime"}, columnType);
	}

	@Override
	public String geneColumnType(Column column) {
		return null;
	}

	@Override
	public String getNumberType(Integer pricision, Integer scale) {
		if(pricision==null || scale==null)
			throw new RuntimeException("can't find precision or scale for number type");
		if(pricision<=10 && scale==0){
			return "int";
		}else if(scale>0) {
			return "double";
		}else{
			throw new RuntimeException("unrecognized number type");
		}
	}

	@Override
	public String getStringType(boolean isVar, Integer length) {
		String type = "char";
		if(isVar){
			type = "varchar";
		}
		if(length!=null){
			type += "("+length+")";
		}
		return type;
	}

}
